home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-9.000 / irsim-9 / src / irsim / hist_io.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  13KB  |  481 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  *    Routines to write and read history dump files
  17.  */
  18.  
  19. #include <stdio.h>
  20. #include "defs.h"
  21. #include "net.h"
  22. #include "ASSERT.h"
  23. #include "bin_io.h"
  24. #include "globals.h"
  25.  
  26.  
  27. private    char    fh_header[] = "#HDUMP#\n";    /* first line of dump file */
  28. private    int    dumph_version = 3;
  29.  
  30.  
  31.     /* define the number of bytes used to read/write history */
  32. #define    NB_HEADER    ( sizeof( fh_header ) - 1 )
  33. #define    NB_NUMBER    4
  34. #define    NB_NDINDEX    4
  35. #define    NB_TIME        4
  36. #define    NB_PVAL        1
  37. #define    NB_RTIME    2
  38. #define    NB_DELAY    2
  39. #define    NB_EVAL        1
  40. #define    NB_VERSION    2
  41.  
  42. #define    MAGIC_NUM( DELTA, NNODES ) ( ((DELTA) ^ (NNODES)) & 0xffff )
  43.  
  44. typedef struct
  45.   {
  46.     char  header[ NB_HEADER ];
  47.     char  hsize[ NB_NUMBER ];
  48.     char  nnodes[ NB_NUMBER ];
  49.     char  cur_delta[ NB_TIME ];
  50.     char  magic[ NB_NUMBER ];
  51.     char  version[ NB_VERSION ];
  52.     char  time0[ NB_TIME ];
  53.   } File_Head;
  54.  
  55. #define    Size_File_Head    ( NB_HEADER + NB_NUMBER + NB_NUMBER + NB_TIME + \
  56.             NB_NUMBER + NB_VERSION + NB_TIME )
  57.  
  58.  
  59. typedef struct            /* format of history header, one per node */
  60.   {
  61.     char  node[ NB_NDINDEX ];    /* node for which history follows */
  62.     char  time[ NB_TIME ];    /* initial time (usually 0) */
  63.     char  pval[ NB_PVAL ];    /* initial packed-value */
  64.   } Node_Head;
  65.  
  66. #define    Size_Node_Head        ( NB_NDINDEX + NB_TIME + NB_PVAL )
  67.  
  68.  
  69. typedef struct        /* format of each history entry */
  70.   {
  71.     char  time[ NB_TIME ];    /* time of this change */
  72.     char  rtime[ NB_RTIME ];    /* input rise time */
  73.     char  delay[ NB_DELAY ];    /* associated delay */
  74.     char  pval[ NB_PVAL ];    /* packed-value (inp, val, punt) */
  75.     char  ptime[ NB_DELAY ];    /* punt time (only punted events) */
  76.   } File_Hist;
  77.  
  78. #define    Size_File_Hist        ( NB_TIME + NB_RTIME + NB_DELAY + NB_PVAL )
  79. #define    Size_Ptime        ( NB_DELAY )
  80. #define    Size_PuntFile_Hist    ( Size_File_Hist + Size_Ptime )
  81.  
  82.  
  83.     /* marks end of history.  Must be same size as Size_File_Hist! */
  84. typedef struct
  85.   {
  86.     char  mark[ NB_TIME ];        /* marker, same for all nodes */
  87.     char  npend[ NB_RTIME ];        /* # of pending events */
  88.     char  dummy1[ NB_DELAY ];        /* just fill the space */
  89.     char  dummy2[ NB_PVAL ];
  90.   } EndHist;
  91.  
  92.  
  93. typedef struct        /* format for pending events */
  94.   {
  95.     char  cause[ NB_NDINDEX ];
  96.     char  time[ NB_TIME ];
  97.     char  delay[ NB_DELAY ];
  98.     char  rtime[ NB_RTIME ];
  99.     char  eval[ NB_EVAL ];
  100.   } File_Pend;
  101.  
  102. #define    Size_File_Pend    (NB_NDINDEX + NB_TIME + NB_DELAY + NB_RTIME + NB_EVAL)
  103.  
  104.  
  105.     /* macros to pack/unpack a value/inp/punt triplet from/to a byte */
  106.  
  107. #define    PACK_VAL( H )        ( (H->inp << 5) | (H->punt << 4) | H->val )
  108. #define    GET_INP( PV )        ( (PV) >> 5 & 1 )
  109. #define    GET_VAL( PV )        ( (PV) & 0x7 )
  110. #define    IS_PUNT( PV )        ( (PV) & 0x10 )
  111.  
  112.  
  113. private    EndHist    h_end =
  114.   {
  115.     { '\0', '\0', '\0', '\040' },        /* mark */
  116.     { '\0', '\0' },                /* npend */
  117.     { '\0', '\0' },                /* dummy1 */
  118.     { '\n' }                    /* dummy2 */
  119.   };
  120.  
  121.  
  122. private int DumpNodeHist( nd, ndindx, fp )
  123.   nptr   nd;
  124.   Ulong  ndindx;
  125.   FILE   *fp;
  126.   {
  127.     register hptr  h;
  128.     Node_Head      header;
  129.     File_Hist      hist;
  130.  
  131.     if( nd->nflags & (POWER_RAIL | ALIAS | MERGED) )
  132.     return( 0 );
  133.  
  134.     PackBytes( header.node, ndindx, NB_NDINDEX );
  135.  
  136.     h = &(nd->head);
  137.     PackBytes( header.time, h->time, NB_TIME );
  138.     PackBytes( header.pval, PACK_VAL( h ), NB_PVAL );
  139.     if( Fwrite( &header, Size_Node_Head, fp ) <= 0 )
  140.     goto abort;
  141.     
  142.     for( h = h->next; h != last_hist; h = h->next )
  143.       {
  144.     PackBytes( hist.time, h->time, NB_TIME );
  145.     PackBytes( hist.pval, PACK_VAL( h ), NB_PVAL );
  146.     if( h->punt )
  147.       {
  148.         PackBytes( hist.delay, h->t.p.delay, NB_DELAY );
  149.         PackBytes( hist.rtime, h->t.p.rtime, NB_RTIME );
  150.         PackBytes( hist.ptime, h->t.p.ptime, NB_DELAY );
  151.         if( Fwrite( &hist, Size_PuntFile_Hist, fp ) <= 0 )
  152.         goto abort;
  153.       }
  154.     else
  155.       {
  156.         PackBytes( hist.delay, h->t.r.delay, NB_DELAY );
  157.         PackBytes( hist.rtime, h->t.r.rtime, NB_RTIME );
  158.         if( Fwrite( &hist, Size_File_Hist, fp ) <= 0 )
  159.         goto abort;
  160.       }
  161.       }
  162.  
  163.     if( nd->events != NULL )
  164.       {
  165.     register evptr  ev;
  166.     register int    n;
  167.     File_Pend       pending;
  168.  
  169.     for( n = 0, ev = nd->events; ev != NULL; ev = ev->nlink, n++ );
  170.     PackBytes( h_end.npend, n, NB_RTIME );
  171.     if( Fwrite( &h_end, Size_File_Hist, fp ) <= 0 )
  172.         goto abort;
  173.     for( ev = nd->events; ev != NULL; ev = ev->nlink )
  174.       {
  175.         ndindx = Node2index( ev->p.cause );
  176.         PackBytes( pending.cause, ndindx, NB_NDINDEX );
  177.         PackBytes( pending.time, ev->ntime, NB_TIME );
  178.         PackBytes( pending.delay, ev->delay, NB_DELAY );
  179.         PackBytes( pending.rtime, ev->rtime, NB_RTIME );
  180.         PackBytes( pending.eval, ev->eval, NB_EVAL );
  181.         if( Fwrite( &pending, Size_File_Pend, fp ) <= 0 )
  182.         goto abort;
  183.       }
  184.       }
  185.     else
  186.       {
  187.     PackBytes( h_end.npend, 0, NB_RTIME );
  188.     if( Fwrite( &h_end, Size_File_Hist, fp ) <= 0 )
  189.         goto abort;
  190.       }
  191.  
  192.     return( 0 );
  193.  
  194.   abort:
  195.     lprintf( stderr, "can't write to file, history dump aborted\n" );
  196.     return( 1 );
  197.   }
  198.  
  199.  
  200. private int WriteHistHeader( fd )
  201.   FILE *fd;
  202.   {
  203.     File_Head  fh;
  204.     long       mag;
  205.  
  206.     mag = MAGIC_NUM( cur_delta, nnodes );
  207.  
  208.     bcopy( fh_header, fh.header, NB_HEADER );
  209.     PackBytes( fh.hsize, GetHashSize(), NB_NUMBER );
  210.     PackBytes( fh.nnodes, nnodes, NB_NUMBER );
  211.     PackBytes( fh.cur_delta, cur_delta, NB_TIME );
  212.     PackBytes( fh.magic, mag, NB_NUMBER );
  213.     PackBytes( fh.version, dumph_version, NB_VERSION );
  214.     PackBytes( fh.time0, sim_time0, NB_TIME );
  215.     if( Fwrite( &fh, Size_File_Head, fd ) <= 0 )
  216.     return( -1 );
  217.     return( 0 );
  218.  }
  219.  
  220.  
  221. private int ReadHistHead( fd, pNewTime, pTime0 )
  222.   FILE  *fd;
  223.   long  *pNewTime, *pTime0;
  224.   {
  225.     File_Head  fh;
  226.     int        n_nodes, hsize, n_version;
  227.     long       newTime, magic, time0;
  228.  
  229.     if( Fread( &fh, Size_File_Head, fd ) != Size_File_Head )
  230.       {
  231.     lprintf( stderr, "ReadHist: can't read file\n" );
  232.     return( -1 );
  233.       }
  234.  
  235.     UnpackBytes( fh.version, n_version, NB_VERSION );
  236.     UnpackBytes( fh.hsize, hsize, NB_NUMBER );
  237.     UnpackBytes( fh.nnodes, n_nodes, NB_NUMBER );
  238.     UnpackBytes( fh.cur_delta, newTime, NB_TIME );
  239.     UnpackBytes( fh.magic, magic, NB_NUMBER );
  240.     UnpackBytes( fh.time0, time0, NB_TIME );
  241.  
  242.     if( strncmp( fh_header, fh.header, NB_HEADER ) != 0 )
  243.       {
  244.     lprintf( stderr, "ReadHist: not a history dump file\n" );
  245.     return( -1 );
  246.       }
  247.  
  248.     if( n_version != dumph_version )
  249.       {
  250.     lprintf( stderr, "ReadHist: Incompatible version: %d\n", n_version );
  251.     return( -1 );
  252.       }
  253.  
  254.     if( (nnodes != n_nodes and nnodes != 0) or hsize != GetHashSize() or
  255.       magic != MAGIC_NUM( newTime, n_nodes ) )
  256.       {
  257.     lprintf( stderr, "ReadHist: incompatible or bad history dump\n" );
  258.     return( -1 );
  259.       }
  260.  
  261.     *pNewTime = newTime;
  262.     *pTime0 = time0;
  263.     return( 0 );
  264.   }
  265.  
  266.  
  267. public void DumpHist( fname )
  268.   char  *fname;
  269.   {
  270.     FILE  *fp;
  271.  
  272.     if( (fp = fopen( fname, "w" )) == NULL )
  273.       {
  274.     lprintf( stderr, "can not open file '%s'\n", fname );
  275.     return;
  276.       }
  277.     
  278.     if( WriteHistHeader( fp ) )
  279.       {
  280.     lprintf( stderr, "can't write to file '%s'\n", fname );
  281.     (void) fclose( fp );
  282.     return;
  283.       }
  284.  
  285.     walk_net_index( DumpNodeHist, fp );
  286.  
  287.     (void) fclose( fp );
  288.   }
  289.  
  290.  
  291. private int rd_hist( fd, pnlist )
  292.   FILE  *fd;
  293.   nptr  *pnlist;
  294.   {
  295.     Node_Head     head;
  296.     File_Hist     hist;
  297.     EndHist       *pe;
  298.     int           inp, val, n, pval, delay, rtime;
  299.     Ulong         ndindx;
  300.     nptr          nd, ndlist;
  301.     long          etime;
  302.     struct Event  ev;
  303.  
  304.     pe = (EndHist *) &hist;
  305.     ndlist = NULL;
  306.     while( Fread( &head, Size_Node_Head, fd ) == Size_Node_Head )
  307.       {
  308.     UnpackBytes( head.node, ndindx, NB_NDINDEX );
  309.     if( (nd = Index2node( ndindx )) == NULL )
  310.       {
  311.         lprintf( stderr, "history read aborted: could not find node\n" );
  312.         *pnlist = ndlist;
  313.         return( -1 );
  314.       }
  315.  
  316.     if( nd->nflags & (POWER_RAIL | ALIAS) )
  317.       {
  318.         lprintf( stderr, "warning: %s should not be in history\n",
  319.           pnode( nd ) );
  320.       }
  321.  
  322.     UnpackBytes( head.time, etime, NB_TIME );
  323.     UnpackBytes( head.pval, pval, NB_PVAL );
  324.     val = GET_VAL( pval );
  325.     inp = GET_INP( pval );
  326.     SetFirstHist( nd, val, inp, etime );
  327.  
  328.     nd->n.next = ndlist;
  329.     ndlist = nd;
  330.  
  331.     if( nd->head.next != last_hist )
  332.         FreeHistList( nd );
  333.  
  334.     while( TRUE )
  335.       {
  336.         if( Fread( &hist, Size_File_Hist, fd ) != Size_File_Hist )
  337.         goto badfile;
  338.         if( bcmp( pe->mark, h_end.mark, NB_TIME ) == 0 )
  339.         break;
  340.         if( nd->nflags & (POWER_RAIL | ALIAS) )
  341.         continue;
  342.         UnpackBytes( hist.time, etime, NB_TIME );
  343.         UnpackBytes( hist.delay, delay, NB_DELAY );
  344.         UnpackBytes( hist.rtime, rtime, NB_RTIME );
  345.         UnpackBytes( hist.pval, pval, NB_PVAL );
  346.         val = GET_VAL( pval );
  347.         inp = GET_INP( pval );
  348.  
  349.         ASSERT( delay < 60000 and delay >= 0 )
  350.           {
  351.         lprintf( stderr, "Error: Corrupted history entry:\n" );
  352.         lprintf( stderr, "\t%s time=%.1f delay=%.1f value=%c\n",
  353.           pnode( nd ), d2ns( etime ), d2ns( delay ), vchars[val] );
  354.           }
  355.         if( IS_PUNT( pval ) )
  356.           {
  357.         if( Fread( hist.ptime, Size_Ptime, fd ) != Size_Ptime )
  358.             goto badfile;
  359.         ev.eval = val;
  360.         ev.ntime = etime;
  361.         ev.delay = delay;
  362.         ev.rtime = rtime;
  363.         UnpackBytes( hist.ptime, delay, NB_DELAY );
  364.         etime -= delay;
  365.               AddPunted( nd, &ev, etime );
  366.           }
  367.         else
  368.         AddHist( nd, val, inp, etime, (long) delay, (long) rtime );
  369.       }
  370.  
  371.     if( not (nd->nflags & POWER_RAIL) )
  372.       {
  373.         nd->npot = nd->curr->val;
  374.         if( nd->curr->inp )
  375.         nd->nflags |= INPUT;
  376.       }
  377.  
  378.     while( nd->events != NULL )    /* get rid of any pending events */
  379.         free_event( nd->events );
  380.  
  381.     UnpackBytes( pe->npend, n, NB_RTIME );
  382.     while( n != 0 )
  383.       {
  384.         File_Pend  pend;
  385.  
  386.         if( Fread( &pend, Size_File_Pend, fd ) != Size_File_Pend )
  387.         goto badfile;
  388.         UnpackBytes( pend.cause, ndindx, NB_NDINDEX );
  389.         UnpackBytes( pend.time, etime, NB_TIME );
  390.         UnpackBytes( pend.delay, delay, NB_DELAY );
  391.         UnpackBytes( pend.rtime, rtime, NB_RTIME );
  392.         UnpackBytes( pend.eval, val, NB_EVAL );
  393.         ASSERT( delay < 60000 and delay >= 0 )
  394.           {
  395.         lprintf( stdout, "Error: Corrupted history entry:\n" );
  396.         lprintf( stdout, "\t%s time=%.1f delay=%.1f value=%c [pnd]\n",
  397.           pnode( nd ), d2ns( etime ), d2ns( delay ), vchars[val] );
  398.         n--;
  399.         continue;
  400.           }
  401.  
  402.         cur_node = Index2node( ndindx );
  403.         cur_delta = etime - delay;            /* fake the delay */
  404.         enqueue_event( nd, val, (long) delay, (long) rtime );
  405.         n--;
  406.       }
  407.       }
  408.  
  409.     *pnlist = ndlist;
  410.     return( 0 );
  411.  
  412.   badfile:
  413.     lprintf( stderr, "premature eof on history file\n" );
  414.     *pnlist = ndlist;
  415.     return( -1 );
  416.   }
  417.  
  418.  
  419. private void fix_transistors( nd )
  420.   register nptr  nd;
  421.   {
  422.     register lptr  l;
  423.  
  424.     while( nd != NULL )
  425.       {
  426.     for( l = nd->ngate; l != NULL; l = l->next )
  427.         l->xtor->state = compute_trans_state( l->xtor );
  428.     nd = nd->n.next;
  429.       }
  430.     for( l = VDD_node->ngate; l != NULL; l = l->next )
  431.     l->xtor->state = compute_trans_state( l->xtor );
  432.     for( l = GND_node->ngate; l != NULL; l = l->next )
  433.     l->xtor->state = compute_trans_state( l->xtor );
  434.   }
  435.  
  436.  
  437. public void ReadHist( fname )
  438.   char  *fname;
  439.   {
  440.     FILE       *fd;
  441.     long       newTime, time0;
  442.     nptr       ndlist;
  443.  
  444.     if( (fd = fopen( fname, "r" )) == NULL )
  445.       {
  446.     lprintf( stderr, "can not open file '%s'\n", fname );
  447.     return;
  448.       }
  449.  
  450.     if( ReadHistHead( fd, &newTime, &time0 ) )
  451.       {
  452.     (void) fclose( fd );
  453.     return;
  454.       }
  455.  
  456.     ClearInputs();
  457.  
  458.     if( rd_hist( fd, &ndlist ) )
  459.       {
  460.     nptr  n;
  461.  
  462.     for( n = ndlist; n != NULL; n = n->n.next )
  463.       {
  464.         FreeHistList( n );            /* undo any work done */
  465.         while( n->events != NULL )
  466.         free_event( n->events );
  467.       }
  468.       }
  469.     else
  470.       {
  471.     sim_time0 = time0;
  472.     cur_delta = newTime;
  473.     if( cur_delta > 0 )
  474.         NoInit();
  475.     if( VDD_node != NULL )
  476.         fix_transistors( ndlist );
  477.       }
  478.  
  479.     (void) fclose( fd );
  480.   }
  481.